---
order: 8
---
# Oracle Connection reset by peer

## 问题现象{#trouble}

环境：

1. Linux服务器
2. Oracle 11g

```java
com.succez.commons.jdbc.SuccezSQLException: (xzzlyk)IO Error: Connection reset by peer
	at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:779)
	at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:921)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1099)
	at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3640)
	at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1384)
	at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3687)
	at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1165)
	at oracle.jdbc.OracleDatabaseMetaData.getTables(OracleDatabaseMetaData.java:2723)
```

## 异常原因{#why}

Oracle JDBC在建立连接时默认读取的Linix的`/dev/random`来产生随机数，但是读取过程可能发送阻塞：

1. Oracle JDBC在建立连接时需要一些随机数据用以加密session token之类的东西，它会读取`/dev/random`设备，`/dev/random`设备会返回小于熵池噪声总数的随机字节。
2. Linux内核熵池，通过搜集键盘，鼠标，中断，磁盘操作来产生随机数据。`/dev/random`可生成高随机性的公钥或一次性密码本。若熵池空了，对`/dev/random`的读操作将会被阻塞，直到收集到了足够的环境噪声为止。
3. `/dev/urandom`则是一个非阻塞的发生器:`dev/random`的一个副本是`/dev/urandom`（”unlocked”，非阻塞的随机数发生器），它会重复使用熵池中的数据以产生伪随机数据。对`/dev/urandom`的读取操作不会产生阻塞，但其输出的熵可能小于`/dev/random`的。
4. 随机数据源默认用的是`/dev/random`。

具体的在java中，是使用`java.security.SecureRandom`产生的随机数：

java.security.SecureRandom is a standard API provided by sun. Among various methods offered by this class `void nextBytes(byte[])` is one. This method is used for generating random bytes.
Oracle 11g JDBC drivers use this API to generate random number during login. Users using Linux have been encountering SQLException("Io exception: Connection reset").

The problem is two fold

1. The JVM tries to list all the files in the /tmp (or alternate tmp directory set by `-Djava.io.tmpdir`) when SecureRandom.nextBytes(byte\[]) is invoked.
   If the number of files is large the method takes a long time to respond and hence cause the server to timeout

2. The method void `nextBytes(byte[])` uses `/dev/random` on Linux and on some machines which lack the random number generating hardware the operation slows down to the extent of bringing the whole login process to a halt.
   Ultimately the the user encounters `SQLException("Io exception: Connection reset")`

Users upgrading to 11g can encounter this issue if the underlying OS is Linux which is running on a faulty hardware.

Cause The cause of this has not yet been determined exactly. It could either be a problem in your hardware or the fact that for some reason the software cannot read from dev/random

Solution Change the setup for your application, so you add the next parameter to the java command:

`-Djava.security.egd=file:/dev/./urandom`

## 解决办法{#solutions}

### 方法一{#solution1}

直接修改$JAVA\_HOME/jre/lib/security路径下的java.security文件。把`securerandom.source=file:/dev/random`修改成`securerandom.source=file:/dev/./urandom`。

### 方法二{#solution2}

tomcat文档里的建议，采用非阻塞的熵源(entropy source)，通过java系统属性来设置：

```java
-Djava.security.egd=file:/dev/./urandom
```

## 参考资料{#references}

1. <https://www.usn-it.de/2009/02/20/oracle-11g-jdbc-driver-hangs-blocked-by-devrandom-entropy-pool-empty/>
2. <https://stackoverflow.com/questions/2327220/oracle-jdbc-intermittent-connection-issue>
3. <https://blog.csdn.net/guodaoying/article/details/52421758?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242>
